﻿using AutoMapper;
using DevExpress.Data.Filtering;
using Newtonsoft.Json;
using System.Linq.Dynamic.Core;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Security.Encryption;
using Volo.Abp.Uow;
using YAKEJI.Abp.Domain.Repositories;
using YAKEJI.Xaf.DataDictionaries;
using YAPACS.BusinessObjects.Exams;
using YAPACS.BusinessObjects.Managements.Devices;
using YAPACS.BusinessObjects.Managements.Exams;
using YAPACS.BusinessObjects.Managements.StoreServices;
using YAPACS.Organizations;
using YAPACS.RisServer.Abstractions;
using YAPACS.RisServer.Services.Dtos;
using YAPACS.RisServer.Workflows.Report;
using YAPACS.Workflows;

namespace YAPACS.RisServer.Services;

public class ReportService(IUnitOfWorkManager unitOfWorkManager, ICurrentUserOrganization currentUserOrganization, IMapper mapper,
    IRepository<Exam, Guid> examRepository, IRepository<Report, Guid> reportRepository, IRepository<ApplicationUser, Guid> userRepository,
    IRepository<Institution, Guid> institutionRepository, IRepository<DepartmentDeviceType> departmentDeviceTypeRepository, IRepository<ExamFlag, Guid> examFlagRepository,
    IGetAdvancedSearchView getAdvancedSearchView, IGetHeaders getHeaders, IGetRowStyle getRowStyle,
    IWriteReport writeReport, ISaveReport saveReport, ISubmitReport submitReport, IAuditReport auditReport, IReviewReport reviewReport, IRevokeReport revokeReport,
    IAdvancedSearchExpression advancedSearchExpression, IGetEApply getEApply, IGetEMedical getEMedical, IGetCriticalValue getCriticalValue,
    IGetRevisitView getRevisitView, IGetFollowUpRecordView getFollowUpRecordView, ISetImageAssessment setImageAssessment, IScore score,
    IMarkFollowUp markFollowUp, IGetReportView getReportView, IGetDefaultFilter getDefaultFilter, IRepository<ReportStyle, Guid> reportStyleRepository,
    IExamListService examListService, IRepository<ReportAudit, Guid> reportAuditRepository, IRepository<ACR, Guid> acrRepository, IRepository<ICD10, Guid> icd10Repository,
    IRepository<UserGroup, Guid> groupRepository, IRepository<DataDictItem, Guid> dataDictItemRepository, IReportExtendsService reportExtendsService,
    IReportStyleService reportStyleService, ICompleteExam completeExam, IBeforeSubmit beforeSubmit, IExamEventService examEventService,
    IRepository<Department, Guid> departmentRepository, IExamPermissionService examPermissionService, IObjectMapper objectMapper, IExamNumberService examNumberService,
    IRepository<ExamItem, Guid> examItemRepository, IRepository<PatientMatter, Guid> patientMatterRepository, IRepository<ExamRemark, Guid> examRemarkRepository,
    IExportService exportService, IStringEncryptionService stringEncryptionService, IReportPdfService reportPdfService, IAccountVerifyService accountVerifyService,
    IRepository<ReportImageQuality, Guid> imageQualityRepository)
    : DomainService, IReportService, ITransientDependency
{
    private readonly IMapper _mapper = mapper;
    private readonly IUnitOfWorkManager _unitOfWorkManager = unitOfWorkManager;
    private readonly ICurrentUserOrganization _currentUserOrganization = currentUserOrganization;
    private readonly IRepository<Exam, Guid> _examRepository = examRepository;
    private readonly IRepository<Report, Guid> _reportRepository = reportRepository;
    private readonly IRepository<ApplicationUser, Guid> _userRepository = userRepository;
    private readonly IRepository<Institution, Guid> _institutionRepository = institutionRepository;
    private readonly IRepository<DepartmentDeviceType> _departmentDeviceTypeRepository = departmentDeviceTypeRepository;
    private readonly IRepository<ExamFlag, Guid> _examFlagRepository = examFlagRepository;
    private readonly IGetAdvancedSearchView _getAdvancedSearchView = getAdvancedSearchView;
    private readonly IGetHeaders _getHeaders = getHeaders;
    private readonly IGetRowStyle _getRowStyle = getRowStyle;
    private readonly IAdvancedSearchExpression _advancedSearchExpression = advancedSearchExpression;
    private readonly IWriteReport _writeReport = writeReport;
    private readonly ISaveReport _saveReport = saveReport;
    private readonly ISubmitReport _submitReport = submitReport;
    private readonly IAuditReport _auditReport = auditReport;
    private readonly IReviewReport _reviewReport = reviewReport;
    private readonly IRevokeReport _revokeReport = revokeReport;
    private readonly IGetEApply _getEApply = getEApply;
    private readonly IGetEMedical _getEMedical = getEMedical;
    private readonly IGetCriticalValue _getCriticalValue = getCriticalValue;
    private readonly IGetRevisitView _getRevisitView = getRevisitView;
    private readonly IGetFollowUpRecordView _getFollowUpRecordView = getFollowUpRecordView;
    private readonly ISetImageAssessment _setImageAssessment = setImageAssessment;
    private readonly IScore _score = score;
    private readonly IMarkFollowUp _markFollowUp = markFollowUp;
    private readonly IGetReportView _getReportView = getReportView;
    private readonly IGetDefaultFilter _getDefaultFilter = getDefaultFilter;
    private readonly IRepository<ReportStyle, Guid> _reportStyleRepository = reportStyleRepository;
    private readonly IExamListService _examListService = examListService;
    private readonly IRepository<ReportAudit, Guid> _reportAuditRepository = reportAuditRepository;
    private readonly IRepository<ACR, Guid> _acrRepository = acrRepository;
    private readonly IRepository<ICD10, Guid> _icd10Repository = icd10Repository;
    private readonly IRepository<UserGroup, Guid> _groupRepository = groupRepository;
    private readonly IRepository<DataDictItem, Guid> _dataDictItemRepository = dataDictItemRepository;
    private readonly IReportExtendsService _reportExtendsService = reportExtendsService;
    private readonly IReportStyleService _reportStyleService = reportStyleService;
    private readonly ICompleteExam _completeExam = completeExam;
    private readonly IBeforeSubmit _beforeSubmit = beforeSubmit;
    private readonly IExamEventService _examEventService = examEventService;
    private readonly IRepository<Department, Guid> _departmentRepository = departmentRepository;
    private readonly IExamPermissionService _examPermissionService = examPermissionService;
    private readonly IObjectMapper _objectMapper = objectMapper;
    private readonly IExamNumberService _examNumberService = examNumberService;
    private readonly IRepository<ExamItem, Guid> _examItemRepository = examItemRepository;
    private readonly IRepository<PatientMatter, Guid> _patientMatterRepository = patientMatterRepository;
    private readonly IRepository<ExamRemark, Guid> _examRemarkRepository = examRemarkRepository;
    private readonly IExportService _exportService = exportService;
    private readonly IStringEncryptionService _stringEncryptionService = stringEncryptionService;
    private readonly IReportPdfService _reportPdfService = reportPdfService;
    private readonly IAccountVerifyService _accountVerifyService = accountVerifyService;
    private readonly IRepository<ReportImageQuality, Guid> _imageQualityRepository = imageQualityRepository;

    private bool ValidatePermission(string permission)
    {
        return true;
    }

    public async Task<WorkflowOutput> GetAdvancedSearchViewAsync()
    {
        try
        {
            var workflowOutput = await _getAdvancedSearchView.InvokeAsync([]);
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetExamListByFilterAsync(DataGridRequest request)
    {
        try
        {
            //获取查询表达式
            CriteriaOperator criteriaOperator = CriteriaOperator.And(CriteriaOperator.FromLambda<Exam>(e => e.ExamStatus > ExamStatus.Appointment));
            var result = await _examListService.GetListByFilterAsync(request, criteriaOperator, _advancedSearchExpression, _getHeaders, _getRowStyle, _getDefaultFilter, ExamFilterType.Exam);
            return result;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput()
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> WriteReportAsync(Guid examId)
    {
        try
        {
            WorkflowOutput workflowOutput = new() { Success = true };
            var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam, isValidateExpertGroup: true);
            if (exam.ExamStatus == ExamStatus.Cancellation)
            {
                throw new Exception("被取消的检查无法书写报告");
            }
            var permission = user.GetUserPermissions().Select(e => e.Name).ToList();
            if (permission.Contains("报告_书写报告"))
            {
                if (exam.Report == null || exam.Report.ReportDoctor == null)
                {
                    if (exam.ExamTime == null)
                    {
                        exam.ExamTime = Clock.Now;
                    }
                    //创建报告对象
                    exam.Report ??= await _reportRepository.NewEntityAsync();
                    //报告医生
                    exam.Report.ReportDoctor = user;
                    //报告机构
                    //用户执业机构
                    exam.Report.ReportInstitution = exam.Report.ReportDoctor.Institution;
                    if (exam.Report.ReportInstitution == null)
                    {
                        if (_currentUserOrganization.InstitutionId.HasValue)
                        {
                            //登录用户选择的医疗机构
                            exam.Report.ReportInstitution = await _institutionRepository.GetAsync(_currentUserOrganization.InstitutionId.Value);
                        }
                    }
                    if (exam.Report.ReportInstitution == null)
                    {
                        //检查设备对应的医疗机构
                        var departmentDeviceType = await _departmentDeviceTypeRepository.FindAsync(e => e.DeviceType == exam.DeviceType);
                        exam.Report.ReportInstitution = departmentDeviceType.Department.Institution;
                    }
                    //报告开始时间
                    exam.Report.ReportStartTime = Clock.Now;
                    //报告状态
                    exam.Report.ReportStatus = ReportStatus.Reporting;
                    exam.ExamStatus = ExamStatus.Report;
                    exam.ReportCandidate = null;
                    //工作流
                    workflowOutput = await _writeReport.InvokeAsync(new WorkflowInput() { { "Report", exam.Report } });
                    if (exam.Report.InitialWritingDoctor != null)
                    {
                        //备份
                    }
                    await _examEventService.AddExamEventAsync(exam, "书写报告");
                }
                else if (exam.Report.ReportStatus == ReportStatus.InitialWriting)
                {
                    throw new Exception($"【{exam.Report.InitialWritingDoctor.Name}({exam.Report.InitialWritingDoctor.JobNumber})】正在初写此报告");
                }
                else if (exam.Report.ReportStatus == ReportStatus.Reporting && exam.Report.ReportDoctor != null && exam.Report.ReportDoctor != user)
                {
                    throw new Exception($"【{exam.Report.ReportDoctor.Name}({exam.Report.ReportDoctor.JobNumber})】正在书写此报告");
                }
            }
            else if (permission.Contains("报告_初写报告"))
            {
                if (exam.Report == null)
                {
                    if (exam.ExamTime == null)
                    {
                        exam.ExamTime = Clock.Now;
                    }
                    //创建报告对象
                    exam.Report = await _reportRepository.NewEntityAsync();
                    //报告医生
                    exam.Report.InitialWritingDoctor = user;
                    //报告机构
                    //用户执业机构
                    exam.Report.InitialWritingInstitution = exam.Report.InitialWritingDoctor.Institution;
                    if (exam.Report.InitialWritingInstitution == null)
                    {
                        if (_currentUserOrganization.InstitutionId.HasValue)
                        {
                            //登录用户选择的医疗机构
                            exam.Report.InitialWritingInstitution = await _institutionRepository.GetAsync(_currentUserOrganization.InstitutionId.Value);
                        }
                    }
                    if (exam.Report.InitialWritingInstitution == null)
                    {
                        //检查设备对应的医疗机构
                        var departmentDeviceType = await _departmentDeviceTypeRepository.FindAsync(e => e.DeviceType == exam.DeviceType);
                        exam.Report.InitialWritingInstitution = departmentDeviceType.Department.Institution;
                    }
                    //报告开始时间
                    exam.Report.InitialWritingStartTime = Clock.Now;
                    //报告状态
                    exam.Report.ReportStatus = ReportStatus.InitialWriting;
                    exam.ExamStatus = ExamStatus.Report;
                    exam.InitialWritingCandidate = null;
                    await _examEventService.AddExamEventAsync(exam, "初写报告");
                }
                else if (exam.Report.ReportStatus == ReportStatus.Reporting && exam.Report.ReportDoctor != null)
                {
                    //已经被书写，不能初写
                    throw new Exception($"【{exam.Report.ReportDoctor.Name}({exam.Report.ReportDoctor.JobNumber})】正在书写此报告");
                }
                else if (exam.Report.ReportStatus == ReportStatus.InitialWriting && exam.Report.InitialWritingDoctor != user)
                {
                    //被别人初写了
                    throw new Exception($"【{exam.Report.InitialWritingDoctor.Name}({exam.Report.InitialWritingDoctor.JobNumber})】正在初写此报告");
                }
            }
            if (exam.Report.ReportStyle == null)
            {
                //根据科室和设备类型 查询默认报告样式
                var reportStyle = await _reportStyleRepository.FirstOrDefaultAsync(e => e.Department == exam.Department && e.DeviceType == exam.DeviceType && e.IsActive && e.IsDefault && e.StyleType == ReportStyleType.Report);
                if (reportStyle == null)
                {
                    var query = await _reportStyleRepository.GetQueryableAsync();
                    query = query.Where(e => e.Department == exam.Department && e.DeviceType == exam.DeviceType && e.IsActive && e.StyleType == ReportStyleType.Report).OrderBy(e => e.Order).ThenBy(e => e.CreationTime);
                    reportStyle = await AsyncExecuter.FirstOrDefaultAsync(query);
                }

                exam.Report.ReportStyle = reportStyle ?? throw new Exception("未找到与检查相关联的报告样式");
            }
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            workflowOutput.Data = exam.Report.Oid;
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            string error = ex.Message;
            await _unitOfWorkManager.Current.RollbackAsync();
            if (ex is AbpDbConcurrencyException)
            {
                var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
                var exam = await _examRepository.GetAsync(examId);
                if (exam.Report != null && exam.Report.ReportDoctor != user)
                {
                    error = $"报告已被【{exam.Report.ReportDoctor.Name}({exam.Report.ReportDoctor.JobNumber})】书写";
                }
            }
            return new WorkflowOutput
            {
                Success = false,
                Error = error
            };
        }
    }

    public async Task<WorkflowOutput> AuditReportAsync(Guid examId)
    {
        var workflowOutput = new WorkflowOutput { Success = true };
        var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
        var exam = await _examRepository.GetAsync(examId);
        await _examPermissionService.ValidateAsync(exam, isValidateExpertGroup: true);
        try
        {
            var permissions = user.GetUserPermissions().Select(e => e.Name).ToList();
            var report = exam.Report ?? throw new Exception("当前检查的报告尚未书写");
            if (permissions.Contains("报告_审核报告") && report.ReportStatus != ReportStatus.Audited)
            {
                if (report.ReportStatus < ReportStatus.Reported)
                {
                    throw new Exception("当前检查的报告还未提交");
                }
                else if (report.ReportStatus == ReportStatus.Reported || report.ReportStatus == ReportStatus.Auditing)
                {
                    workflowOutput = await AuditAsync(exam, report, user);
                }
                else if (report.ReportStatus == ReportStatus.Reviewing)
                {
                    throw new Exception($"当前检查的报告正在复审中");
                }
            }
            else if (permissions.Contains("报告_复审报告"))
            {
                if (report.ReportStatus < ReportStatus.Audited)
                {
                    throw new Exception("当前检查的报告还未审核");
                }
                else if (report.ReportStatus == ReportStatus.Audited || report.ReportStatus == ReportStatus.Reviewing)
                {
                    workflowOutput = await ReviewAsync(exam, report, user);
                }
            }
            workflowOutput.Data = exam.Report.Oid;
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            string error = ex.Message;
            if (ex is AbpDbConcurrencyException)
            {
                if (exam.Report.ReviewDoctor != null && exam.Report.ReviewDoctor != user)
                {
                    error = $"报告已被【{exam.Report.ReviewDoctor.Name}({exam.Report.ReviewDoctor.JobNumber})】复审";
                }
                else if (exam.Report.AuditDoctor != null && exam.Report.AuditDoctor != user)
                {
                    error = $"报告已被【{exam.Report.AuditDoctor.Name}({exam.Report.AuditDoctor.JobNumber})】审核";
                }
            }
            workflowOutput.Error = error;
            workflowOutput.Success = false;
            return workflowOutput;
        }
    }

    private async Task<WorkflowOutput> AuditAsync(Exam exam, Report report, ApplicationUser user)
    {
        var workflowOutput = new WorkflowOutput { Success = true };
        if (report.AuditDoctor == null)
        {
            exam.ExamStatus = ExamStatus.Audit;
            workflowOutput = await _auditReport.InvokeAsync(new WorkflowInput { { "Report", report } });
            report.AuditStartTime = Clock.Now;
            report.AuditDoctor = user;
            //审核机构
            //用户执业机构
            report.AuditInstitution = report.AuditDoctor.Institution;
            if (report.AuditInstitution == null)
            {
                if (_currentUserOrganization.InstitutionId.HasValue)
                {
                    //登录用户选择的医疗机构
                    report.AuditInstitution = await _institutionRepository.GetAsync(_currentUserOrganization.InstitutionId.Value);
                }
            }
            if (report.AuditInstitution == null)
            {
                //检查设备对应的医疗机构
                var departmentDeviceType = await _departmentDeviceTypeRepository.FindAsync(e => e.DeviceType == report.Exam.DeviceType);
                report.AuditInstitution = departmentDeviceType.Department.Institution;
            }
            //报告状态
            report.ReportStatus = ReportStatus.Auditing;

            await _examEventService.AddExamEventAsync(report.Exam, "审核报告");
        }
        else if (report.AuditDoctor != null)
        {
            if (report.AuditDoctor != user)
            {
                throw new Exception($"【{report.AuditDoctor.Name}({report.AuditDoctor.JobNumber})】正在审核此报告");
            }
        }
        return workflowOutput;
    }

    private async Task<WorkflowOutput> ReviewAsync(Exam exam, Report report, ApplicationUser user)
    {
        var workflowOutput = new WorkflowOutput { Success = true };

        if (report.ReviewDoctor == null)
        {
            exam.ExamStatus = ExamStatus.Review;
            workflowOutput = await _reviewReport.InvokeAsync(new WorkflowInput { { "Report", report } });
            report.ReviewStartTime = Clock.Now;
            report.ReviewDoctor = user;
            //审核机构
            //用户执业机构
            report.ReviewInstitution = report.ReviewDoctor.Institution;
            if (report.ReviewInstitution == null)
            {
                if (_currentUserOrganization.InstitutionId.HasValue)
                {
                    //登录用户选择的医疗机构
                    report.ReviewInstitution = await _institutionRepository.GetAsync(_currentUserOrganization.InstitutionId.Value);
                }
            }
            if (report.ReviewInstitution == null)
            {
                //检查设备对应的医疗机构
                var departmentDeviceType = await _departmentDeviceTypeRepository.FindAsync(e => e.DeviceType == report.Exam.DeviceType);
                report.ReviewInstitution = departmentDeviceType.Department.Institution;
            }
            //报告状态
            report.ReportStatus = ReportStatus.Reviewing;

            await _examEventService.AddExamEventAsync(report.Exam, "复审报告");
        }
        else if (report.ReviewDoctor != null)
        {
            if (report.ReviewDoctor != user)
            {
                throw new Exception($"【{report.ReviewDoctor.Name}({report.ReviewDoctor.JobNumber})】正在复审报告");
            }
        }
        return workflowOutput;
    }

    public async Task<WorkflowOutput> GetExamAsync(Guid reportId)
    {
        try
        {
            var workflowOutput = new WorkflowOutput { Success = true };

            var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
            var report = await _reportRepository.GetAsync(reportId);
            report.ImageOpinion = "||无||";

            List<string> userPermissions = [];
            var permissions = user.GetUserPermissions().Select(e => e.Name).ToList();

            if (permissions.Contains("报告_初写报告") && report.InitialWritingDoctor == user)
            {
                if (report.ReportStatus == ReportStatus.InitialWriting)
                {
                    report.IsEditing = true;
                    userPermissions.Add("报告_保存");
                    userPermissions.Add("报告_提交报告");
                    userPermissions.Add("报告_切换报告样式");
                    userPermissions.Add("报告_放弃书写");
                }
                else if (report.ReportStatus == ReportStatus.InitialWritten)
                {
                    userPermissions.Add("报告_撤回");
                }
            }

            if (permissions.Contains("报告_书写报告") && report.ReportDoctor == user)
            {
                if (report.ReportStatus == ReportStatus.Reporting)
                {
                    if (report.InitialWritingDoctor == null)
                    {
                        report.IsEditing = true;
                        userPermissions.Add("报告_保存");
                        userPermissions.Add("报告_提交报告");
                        userPermissions.Add("报告_切换报告样式");
                        userPermissions.Add("报告_放弃书写");
                    }
                    else
                    {
                        userPermissions.Add("报告_修正报告");
                        userPermissions.Add("报告_保存");
                        userPermissions.Add("报告_提交报告");
                        userPermissions.Add("报告_驳回重写");
                    }
                }
                else if (report.ReportStatus == ReportStatus.Reported)
                {
                    userPermissions.Add("报告_撤回");
                }
            }

            if (permissions.Contains("报告_审核自审") && report.ReportDoctor == user)
            {
                if (report.ReportStatus == ReportStatus.Reported)
                {
                    userPermissions.Add("报告_审核报告");
                }

                if (report.IsEditing)
                {
                    userPermissions.Add("报告_切换报告样式");
                }
            }

            if (permissions.Contains("报告_审核报告"))
            {
                if (report.AuditDoctor == user ||
                    (report.ReportDoctor == user &&
                        permissions.Contains("报告_审核自审") &&
                        permissions.Contains("报告_验密审核")))
                {
                    if (report.ReportStatus == ReportStatus.Auditing)
                    {
                        userPermissions.Add("报告_修正报告");
                        userPermissions.Add("报告_通过审核");
                        userPermissions.Add("报告_申请复审");
                        userPermissions.Add("报告_驳回重写");
                    }

                    if ((report.ReportStatus == ReportStatus.Audited || report.ReportStatus == ReportStatus.Completed) && report.ReviewDoctor == null)
                    {
                        userPermissions.Add("报告_撤回");
                    }
                }
            }

            if (permissions.Contains("报告_复审报告") && report.ReviewDoctor == user)
            {
                if (report.ReportStatus == ReportStatus.Reviewing)
                {
                    userPermissions.Add("报告_修正报告");
                    userPermissions.Add("报告_通过审核");
                    userPermissions.Add("报告_驳回重写");
                }

                if ((report.ReportStatus == ReportStatus.Reviewed || report.ReportStatus == ReportStatus.Completed) && report.ReviewDoctor != null)
                {
                    userPermissions.Add("报告_撤回");
                }
            }

            if (permissions.Contains("报告_审核报告") && report.ReportStatus == ReportStatus.Reported)
            {
                //不是自己书写的可以审核
                if (report.AuditDoctor == null && report.ReportDoctor != user)
                {
                    userPermissions.Add("报告_审核报告");
                }
            }

            if (permissions.Contains("报告_复审报告") && report.ReportStatus == ReportStatus.Audited)
            {
                //不是自己审核的可以复审
                if (report.ReviewDoctor == null && report.AuditDoctor != user)
                {
                    userPermissions.Add("报告_复审报告");
                }
            }

            var examDto = _mapper.Map<ExamDto>(report.Exam);
            if (report.InitialWritingDoctor == user || report.ReportDoctor == user || report.AuditDoctor == user || report.ReviewDoctor == user)
            {
                examDto.Report.ReadOnly = false;
            }

            if (!report.ReportStatus.Equals(ReportStatus.Completed))
            {
                var schema = await _reportExtendsService.GetSchemaAsync(report.Oid);
                examDto.Report.ReportExtendingSchema = schema == null ? null : JsonConvert.SerializeObject(schema);
            }

            examDto.Report.Permissions = userPermissions.Distinct().ToArray();

            if (examDto.Report.ReportStyle != null)
            {
                examDto.Report.ReportStyle.DisplayName = _reportStyleService.GetDisplayName(examDto.Report.ReportStyle.DisplayName);
            }

            workflowOutput.Data = examDto;

            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetExamViewAsync(Guid reportId)
    {
        try
        {
            var report = await _reportRepository.GetAsync(reportId);
            var workflowOutput = await _getReportView.InvokeAsync(new WorkflowInput { { "Exam", report.Exam } });
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> SaveReportAsync(ReportDto reportDto)
    {
        try
        {
            var report = await _reportRepository.GetAsync(reportDto.Oid);
            await Save(report, reportDto);
            var workflowOutput = await _saveReport.InvokeAsync(new WorkflowInput { { "Report", report } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> SubmitReportAsync(Guid reportId, Guid? auditUserId, bool complete)
    {
        try
        {
            var now = DateTime.Now;

            var report = await _reportRepository.GetAsync(reportId);
            if (report.ReportStatus == ReportStatus.InitialWritten || report.ReportStatus == ReportStatus.Reported || report.ReportStatus == ReportStatus.Audited || report.ReportStatus == ReportStatus.Reviewed)
            {
                throw new Exception("报告已经提交，请勿重复提交");
            }
            else if (report.ReportStatus == ReportStatus.Completed)
            {
                throw new Exception("当前检查的报告已完成，无需再次提交");
            }
            var workflowOutput = await _beforeSubmit.InvokeAsync(new WorkflowInput { { "Report", report } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            if (report.Exam.ExamQueuing != null && report.Exam.ExamQueuing.Status != ExamQueuingStatus.Completed)
            {
                report.Exam.ExamQueuing.Status = ExamQueuingStatus.Completed;
            }

            var eventName = "提交报告";

            if (report.ReportStatus == ReportStatus.InitialWriting)
            {
                if (report.InitialWritingStartTime == null)
                {
                    report.InitialWritingStartTime = Clock.Now;
                }

                //报告时间
                report.InitialWritingTime = Clock.Now;
                //报告状态
                report.ReportStatus = ReportStatus.InitialWritten;

                eventName = "提交报告";
            }
            if (report.ReportStatus == ReportStatus.Reporting)
            {
                if (report.ReportStartTime == null)
                {
                    report.ReportStartTime = Clock.Now;
                }

                //报告时间
                report.ReportTime = Clock.Now;
                //报告状态
                report.ReportStatus = ReportStatus.Reported;

                if (complete)
                {
                    if (report.AuditStartTime == null)
                    {
                        report.AuditStartTime = Clock.Now;
                    }

                    //审核时间
                    report.AuditTime = Clock.Now;
                    //报告状态
                    report.ReportStatus = ReportStatus.Audited;

                    if (auditUserId.HasValue)
                    {
                        report.AuditDoctor = await _userRepository.GetAsync(auditUserId.Value);
                        report.AuditInstitution = report.AuditDoctor.Institution ?? report.ReportInstitution;
                    }
                    else
                    {
                        report.AuditDoctor = report.ReportDoctor;
                        report.AuditInstitution = report.ReportDoctor.Institution;
                    }

                    eventName = "通过审核";
                }
                else
                {
                    eventName = "提交报告";
                }
            }
            else if (report.ReportStatus == ReportStatus.Auditing)
            {
                if (report.AuditStartTime == null)
                {
                    report.AuditStartTime = Clock.Now;
                }

                //审核时间
                report.AuditTime = Clock.Now;
                //报告状态
                report.ReportStatus = ReportStatus.Audited;

                if (auditUserId.HasValue)
                {
                    report.AuditDoctor = await _userRepository.GetAsync(auditUserId.Value);
                    report.AuditInstitution = report.AuditDoctor.Institution ?? report.ReportInstitution;
                }

                if (complete)
                {
                    eventName = "通过审核";
                }
                else
                {
                    eventName = "申请复审";
                }
            }
            else if (report.ReportStatus == ReportStatus.Reviewing)
            {
                if (report.ReviewStartTime == null)
                {
                    report.ReviewStartTime = Clock.Now;
                }

                //复审时间
                report.ReviewTime = Clock.Now;
                report.CompletedTime = Clock.Now;
                //报告状态
                report.ReportStatus = ReportStatus.Completed;

                eventName = "通过复审";
            }

            //通过审核直接完成
            if (complete)
            {
                report.CompletedTime = Clock.Now;
                report.ReportStatus = ReportStatus.Completed;
            }
            if (report.ReportStatus == ReportStatus.Completed)
            {
                report.Exam.CompletedTime = Clock.Now;
                report.Exam.ExamStatus = ExamStatus.Completed;

                workflowOutput = await _completeExam.InvokeAsync(new WorkflowInput { { "Exam", report.Exam } });
                await _reportPdfService.GeneratePdfFileAsync(report, ReportStyleType.Report);
            }
            else
            {
                workflowOutput = await _submitReport.InvokeAsync(new WorkflowInput { { "Report", report } });
                if (!workflowOutput.Success)
                {
                    throw new Exception(workflowOutput.Error);
                }
            }

            report.IsEditing = false;

            await _examEventService.AddExamEventAsync(report.Exam, eventName);

            Console.WriteLine(DateTime.Now - now);

            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    private async Task Save(Report report, ReportDto reportDto)
    {
        report.Exam.Patient.PhoneNumber = reportDto.PhoneNumber;
        report.ExamResult = (ExamResult?)reportDto.ExamResult;
        report.ImageSeeing = reportDto.ImageSeeing;
        report.ImageDiagnosis = reportDto.ImageDiagnosis;
        report.ImageOpinion = reportDto.ImageOpinion;
        report.ReportExtending = reportDto.ReportExtending;
        report.ReportExtendingSchema = reportDto.ReportExtendingSchema;

        if (reportDto.ReportImageQuality != null)
        {
            ReportImageQuality reportImageQuality = await _imageQualityRepository.GetAsync(e => e.Oid == reportDto.ReportImageQuality);
            report.ReportImageQuality = reportImageQuality;
        }
        else
        {
            report.ReportImageQuality = null;
        }




        if (reportDto.ReportStyle != null)
        {
            var reportStyle = await _reportStyleRepository.FindAsync(reportDto.ReportStyle.Id);
            if (reportStyle != null)
            {
                report.ReportStyle = reportStyle;
            }
        }
        report.ACRs.RemoveAll(e => true);
        var acrs = await _acrRepository.GetListAsync(e => reportDto.ACRs.Contains(e.Oid));
        report.ACRs.AddRange(acrs);
        report.ICD10s.RemoveAll(e => true);
        var icd10s = await _icd10Repository.GetListAsync(e => reportDto.ICD10s.Contains(e.Oid));
        report.ICD10s.AddRange(icd10s);
    }

    public async Task<WorkflowOutput> RevokeReportAsync(Guid examId, Guid reviseType, string reason)
    {
        try
        {
            var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam, isValidateExpertGroup: true);
            var report = exam.Report;
            switch (report.ReportStatus)
            {
                case ReportStatus.InitialWriting:
                    throw new Exception("正在初写此检查的报告");
                case ReportStatus.Reporting:
                    throw new Exception("正在编辑此检查的报告");
                case ReportStatus.Auditing:
                    throw new Exception("正在审核此检查的报告");
                case ReportStatus.Reviewing:
                    throw new Exception("正在复审此检查的报告");
                default:
                    break;
            }
            bool canRevoke = true;
            switch (report.ReportStatus)
            {
                case ReportStatus.InitialWritten:
                    canRevoke = report.InitialWritingDoctor == user;
                    break;
                case ReportStatus.Reported:
                    canRevoke = report.ReportDoctor == user;
                    break;
                case ReportStatus.Audited:
                    canRevoke = report.AuditDoctor == user;
                    break;
                case ReportStatus.Reviewed:
                    canRevoke = report.ReviewDoctor == user;
                    break;
                case ReportStatus.Completed:
                    if (report.ReviewDoctor != null)
                    {
                        canRevoke = report.ReviewDoctor == user;
                    }
                    else if (report.AuditDoctor != null)
                    {
                        canRevoke = report.AuditDoctor == user;
                        if (!canRevoke)
                        {
                            var permissions = user.GetUserPermissions().Select(e => e.Name).ToList();
                            if (report.ReportDoctor == user && permissions.Contains("报告_审核自审") && permissions.Contains("报告_验密审核"))
                            {
                                canRevoke = true;
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
            if (!canRevoke)
            {
                throw new Exception("不能撤回非本人提交的报告");
            }
            var workflowOutput = await _revokeReport.InvokeAsync(new WorkflowInput { { "Report", report } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }

            string eventName = "撤回报告";

            if (report.ReportStatus == ReportStatus.InitialWritten)
            {
                exam.ExamStatus = ExamStatus.Report;
                //报告时间
                report.InitialWritingTime = null;
                //报告状态
                report.ReportStatus = ReportStatus.InitialWriting;

                eventName = "撤回提交";
            }
            if (report.ReportStatus == ReportStatus.Reported)
            {
                exam.ExamStatus = ExamStatus.Report;
                //报告时间
                report.ReportTime = null;
                //报告状态
                report.ReportStatus = ReportStatus.Reporting;

                eventName = "撤回提交";
            }
            else if (report.ReportStatus == ReportStatus.Audited)
            {
                exam.ExamStatus = ExamStatus.Audit;
                //报告时间
                report.AuditTime = null;
                //报告状态
                report.ReportStatus = ReportStatus.Auditing;

                eventName = "撤回审核";
            }
            else if (report.ReportStatus == ReportStatus.Reviewed)
            {
                exam.ExamStatus = ExamStatus.Review;
                //报告时间
                report.ReviewTime = null;
                //报告状态
                report.ReportStatus = ReportStatus.Reviewing;

                eventName = "撤回审核";
            }
            else if (report.ReportStatus == ReportStatus.Completed)
            {
                if (report.ReviewDoctor != null)
                {
                    exam.ExamStatus = ExamStatus.Review;
                    //报告时间
                    report.ReviewTime = null;
                    //报告状态
                    report.ReportStatus = ReportStatus.Reviewing;
                }
                else if (report.AuditDoctor != null)
                {
                    exam.ExamStatus = ExamStatus.Audit;
                    //报告时间
                    report.AuditTime = null;
                    //报告状态
                    report.ReportStatus = ReportStatus.Auditing;
                }

                eventName = "撤回审核";
            }
            report.IsEditing = true;
            //删除报告文件
            await _reportPdfService.DeletePdfFileAsync(report);
            await CreateReportAuditAsync(report, reviseType, eventName, reason);
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    private async Task CreateReportAuditAsync(Report report, Guid reviseType, string eventName, string reason)
    {
        var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
        var group = await _groupRepository.GetAsync(_currentUserOrganization.UserGroupId.Value);
        var reportAudit = await _reportAuditRepository.NewEntityAsync();
        reportAudit.ExamResult = report.ExamResult;
        reportAudit.ImageSeeing = report.ImageSeeing;
        reportAudit.ImageDiagnosis = report.ImageDiagnosis;
        reportAudit.ImageOpinion = report.ImageOpinion;
        reportAudit.ReportExtending = report.ReportExtending;
        reportAudit.ICD10s.AddRange(report.ICD10s);
        reportAudit.ACRs.AddRange(report.ACRs);
        reportAudit.ReviseDoctor = user;
        reportAudit.ReviseDepartment = group.Department;
        reportAudit.ReviseInstitution = reportAudit.ReviseDoctor.Institution;
        reportAudit.ReviseTime = Clock.Now;
        reportAudit.ReviseType = await _dataDictItemRepository.GetAsync(reviseType);
        reportAudit.ReviseReason = reason;
        if (reportAudit.ReviseInstitution == null)
        {
            if (_currentUserOrganization.InstitutionId.HasValue)
            {
                //登录用户选择的医疗机构
                reportAudit.ReviseInstitution = await _institutionRepository.GetAsync(_currentUserOrganization.InstitutionId.Value);
            }
        }
        if (reportAudit.ReviseInstitution == null)
        {
            //检查设备对应的医疗机构
            var departmentDeviceType = await _departmentDeviceTypeRepository.FindAsync(e => e.DeviceType == report.Exam.DeviceType);
            reportAudit.ReviseInstitution = departmentDeviceType.Department.Institution;
        }
        report.ReportAudits.Add(reportAudit);
        await _examEventService.AddExamEventAsync(report.Exam, eventName, $"类型：{reportAudit.ReviseType.Name}，原因：{reason}");
    }

    public async Task<WorkflowOutput> AmendReportAsync(Guid examId, Guid reviseType, string reason)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam, isValidateExpertGroup: true);
            var report = exam.Report;
            report.IsEditing = true;
            await CreateReportAuditAsync(report, reviseType, "修正报告", reason);
            return new WorkflowOutput { Success = true };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> RejectReportAsync(Guid examId, Guid reviseType, string reason)
    {
        try
        {
            //报告医生驳回给实习生
            //审核/复核医生驳回给报告医生
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam, isValidateExpertGroup: true);
            var report = exam.Report;
            if (report != null)
            {
                if (report.ReportStatus == ReportStatus.Reporting && report.InitialWritingDoctor != null)
                {
                    report.ReportStatus = ReportStatus.InitialWriting;
                    report.ReportDoctor = null;
                    report.ReportStartTime = null;
                    report.ReportInstitution = null;
                }
                if (report.ReportStatus == ReportStatus.Auditing || report.ReportStatus == ReportStatus.Reviewing)
                {
                    report.ReportStatus = ReportStatus.Reporting;
                    report.AuditDoctor = null;
                    report.AuditStartTime = null;
                    report.AuditInstitution = null;
                    report.ReviewDoctor = null;
                    report.ReviewStartTime = null;
                    report.ReviewInstitution = null;
                }
            }
            report.IsEditing = true;
            await CreateReportAuditAsync(report, reviseType, "驳回重写", reason);
            return new WorkflowOutput { Success = true };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> CollectAsync(List<Guid> examIds, List<Guid> examFlagIds)
    {
        try
        {
            var examFlags = await _examFlagRepository.GetListAsync(e => examFlagIds.Contains(e.Id));
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            var single = examIds.Count == 1;
            exams.ForEach(exam =>
            {
                if (single)
                {
                    exam.ExamFlags.RemoveAll(e => true);
                }
                //选择多条，追加收藏
                exam.ExamFlags.AddIfNotContains(examFlags);
            });
            return new WorkflowOutput
            {
                Success = true
            };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> CancelCollectAsync(List<Guid> examIds, List<Guid> examFlagIds)
    {
        try
        {
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            exams.ForEach(exam =>
            {
                exam.ExamFlags.RemoveAll(e => examFlagIds.Contains(e.Id));
            });
            return new WorkflowOutput
            {
                Success = true
            };
        }
        catch (Exception ex)
        {
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetCollectionMenuAsync(List<Guid> examIds, bool collect)
    {
        try
        {
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            var examFlags = new List<ExamFlag>();
            if (_currentUserOrganization != null
                && _currentUserOrganization.UserGroupId.HasValue
                && _currentUserOrganization.DepartmentId.HasValue)
            {
                var query = await _examFlagRepository.GetListAsync(e => e.IsActive);
                //查询个人过滤
                var userFlags = query.Where(e => e.User != null && e.User.Oid == _currentUserOrganization.UserId);
                examFlags.AddIfNotContains(userFlags);
                //查询小组过滤
                var groupFlags = query.Where(e => e.Department != null && e.Department.Oid == _currentUserOrganization.DepartmentId.Value
                && e.UserGroup != null && e.UserGroup.Oid == _currentUserOrganization.UserGroupId.Value && e.User == null);
                examFlags.AddIfNotContains(groupFlags);
                //查询科室过滤
                var departmentFlags = query.Where(e => e.Department != null && e.Department.Oid == _currentUserOrganization.DepartmentId.Value && e.UserGroup == null);
                examFlags.AddIfNotContains(departmentFlags);
            }
            var single = exams.Count == 1;
            var examFlagItems = examFlags
                .OrderBy(f => f.IsDirectory ? 0 : 1)
                .ThenBy(f => f.Order)
                .Select(e => new
                {
                    Id = e.Oid,
                    ParentId = e.Parent?.Oid,
                    Text = e.Name,
                    e.IsDirectory,
                    Collected = collect && single && exams[0].ExamFlags.Any(f => f == e),
                    Expanded = true
                });
            return new WorkflowOutput
            {
                Success = true,
                Data = examFlagItems
            };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetCriticalValueAsync(Guid reportId)
    {
        try
        {
            var report = await _reportRepository.GetAsync(reportId);
            var workflowOutput = await _getCriticalValue.InvokeAsync(new WorkflowInput { { "Report", report } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetEApplyAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            var workflowOutput = await _getEApply.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetEMedicalAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            var workflowOutput = await _getEMedical.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetFollowUpRecordAsync(Guid reportId)
    {
        try
        {
            var report = await _reportRepository.GetAsync(reportId);
            var workflowOutput = await _getFollowUpRecordView.InvokeAsync(new WorkflowInput { { "Report", report } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> ImageAssessmentAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            var workflowOutput = await _setImageAssessment.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> MarkFollowUpAsync(Guid reportId)
    {
        try
        {
            var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
            var report = await _reportRepository.GetAsync(reportId);
            if (report.InitialWritingDoctor != user && report.ReportDoctor != user && report.AuditDoctor != user && report.ReviewDoctor != user)
            {
                throw new Exception("没有权限标记随访");
            }
            var workflowOutput = await _markFollowUp.InvokeAsync(new WorkflowInput { { "Report", report } });
            report.IsFollowup = !report.IsFollowup;
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            await _examEventService.AddExamEventAsync(report.Exam, report.IsFollowup ? "标记随访" : "取消随访");
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> RevisitAsync(Guid reportId)
    {
        try
        {
            var report = await _reportRepository.GetAsync(reportId);
            var workflowOutput = await _getRevisitView.InvokeAsync(new WorkflowInput { { "Report", report } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> ScoreAsync(Guid examId)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            var workflowOutput = await _score.InvokeAsync(new WorkflowInput { { "Exam", exam } });
            if (!workflowOutput.Success)
            {
                throw new Exception(workflowOutput.Error);
            }
            return workflowOutput;
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GetPdfFileAsync(IList<Guid> examIds, ReportStyleType reportStyleType)
    {
        try
        {
            List<string> errors = [];
            List<string> reportFiles = [];
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            foreach (var exam in exams)
            {
                if (exam.Report == null)
                {
                    errors.Add($"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】未书写报告");
                }
                else if (exam.Report.ReportStatus < ReportStatus.Audited && reportStyleType == ReportStyleType.Report)
                {
                    errors.Add($"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】报告未审核");
                }
                else
                {
                    var success = false;
                    var container = exam.StoreService.GetBlobContainer();
                    var exist = await container.ExistsAsync(exam.Report.ReportFile);
                    if (exist)
                    {
                        reportFiles.Add(exam.Report.ReportUrl);
                        success = true;
                    }
                    else
                    {
                        if (await _reportPdfService.GeneratePdfFileAsync(exam.Report, reportStyleType))
                        {
                            reportFiles.Add(exam.Report.ReportUrl);
                            success = true;
                        }
                        else
                        {
                            errors.Add($"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】未选择报告样式");
                        }
                    }

                    if (success)
                    {
                        exam.Report.PrintingTimes += 1;
                        exam.Report.LastPrintingTime = Clock.Now;
                    }
                }
            }

            return new WorkflowOutput { Success = true, Data = reportFiles, Error = string.Join("/r/n", errors) };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }
    public async Task<WorkflowOutput> GeneratePdfFileAsync(IList<Guid> examIds, ReportStyleType reportStyleType)
    {
        try
        {
            List<string> errors = [];
            List<string> reportFiles = [];
            var exams = await _examRepository.GetListAsync(e => examIds.Contains(e.Oid));
            foreach (var exam in exams)
            {
                if (exam.Report == null)
                {
                    errors.Add($"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】未书写报告");
                }
                else if (exam.Report.ReportStatus < ReportStatus.Audited && reportStyleType == ReportStyleType.Report)
                {
                    errors.Add($"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】报告未审核");
                }
                else
                {
                    var container = exam.StoreService.GetBlobContainer();
                    if (await _reportPdfService.GeneratePdfFileAsync(exam.Report, reportStyleType))
                    {
                        reportFiles.Add(exam.Report.ReportUrl);
                    }
                    else
                    {
                        errors.Add($"当前检查【{exam.Patient.Name}({exam.AccessionNumber})】未选择报告样式");
                    }
                }
            }

            return new WorkflowOutput { Success = true, Data = reportFiles, Error = string.Join("/r/n", errors) };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }
    public async Task<WorkflowOutput> UpdateExamReportStyleAsync(Guid reportId, ReportDto reportDto)
    {
        try
        {
            var report = await _reportRepository.GetAsync(reportId);
            await Save(report, reportDto);
            return new WorkflowOutput { Success = true };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> GiveUpWriteReportAsync(Guid reportId)
    {
        try
        {
            var report = await _reportRepository.GetAsync(reportId);
            var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
            if ((report.ReportStatus == ReportStatus.InitialWriting && report.InitialWritingDoctor == user)
                || (report.ReportStatus == ReportStatus.Reporting && report.ReportDoctor == user && report.InitialWritingDoctor == null))
            {
                await _examEventService.AddExamEventAsync(report.Exam, "放弃书写");
                report.Exam.ExamStatus = ExamStatus.Report;
                await _reportRepository.DeleteAsync(report);
                report.Exam.Report = null;
            }
            return new WorkflowOutput { Success = true };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> TransferReportAsync(WorkflowInput input, string nextApi = null)
    {
        try
        {
            var reportIds = JsonConvert.DeserializeObject<IList<Guid>>(input.GetValueOrDefault("reportIds").ToString() ?? "[]");
            if (reportIds.Count == 0)
            {
                return new WorkflowOutput
                {
                    Success = false,
                    Error = "没有找到需要移交的检查"
                };
            }
            var department = await _departmentRepository.GetAsync(_currentUserOrganization.DepartmentId.Value);
            var reports = await _reportRepository.GetListAsync(e => reportIds.Contains(e.Oid));
            List<string> errMessages = [];
            foreach (var report in reports)
            {
                if (report.Exam.Department != department)
                {
                    errMessages.Add($"检查号{report.Exam.AccessionNumber}不属于本科室");
                }
            }
            if (errMessages.Count > 0)
            {
                throw new Exception(string.Join("<br />", errMessages));
            }
            if (input.ContainsKey("userId"))
            {
                var userIdString = input.GetValueOrDefault("userId")?.ToString();
                var userId = Guid.Parse(userIdString);
                var transferUser = await _userRepository.GetAsync(userId);
                foreach (var report in reports)
                {
                    var examInfo = $"【{report.Exam.Patient.Name}({report.Exam.AccessionNumber})】";
                    if (report.ReportStatus == ReportStatus.InitialWritten || report.ReportStatus == ReportStatus.Reported || report.ReportStatus == ReportStatus.Audited)
                    {
                        return new WorkflowOutput
                        {
                            Success = false,
                            Error = $"{examInfo}没有处于锁住状态，不需要进行移交"
                        };
                    }
                    else if (report.ReportStatus == ReportStatus.Completed)
                    {
                        return new WorkflowOutput
                        {
                            Success = false,
                            Error = $"{examInfo}报告已完成，不能进行移交"
                        };
                    }

                    ApplicationUser oldDoctor = null;

                    if (report.ReviewDoctor != null)
                    {
                        oldDoctor = report.ReviewDoctor;
                        report.ReviewDoctor = transferUser;
                    }
                    else if (report.AuditDoctor != null)
                    {
                        oldDoctor = report.AuditDoctor;
                        report.AuditDoctor = transferUser;
                    }
                    else if (report.ReportDoctor != null)
                    {
                        oldDoctor = report.ReportDoctor;
                        report.ReportDoctor = transferUser;
                    }
                    else
                    {
                        oldDoctor = report.InitialWritingDoctor;
                        report.InitialWritingDoctor = transferUser;
                    }

                    await _examEventService.AddExamEventAsync(report.Exam, "移交报告", $"报告从【{oldDoctor.Name}】移交给【{transferUser.Name}】");
                }
                return new WorkflowOutput { Success = true };
            }
            else
            {
                var userName = input.GetValueOrDefault("userName")?.ToString();
                var password = input.GetValueOrDefault("password")?.ToString();
                if (string.IsNullOrWhiteSpace(userName))
                {
                    var workflowOutput = await _accountVerifyService.GetVerifyViewAsync();
                    if (!string.IsNullOrWhiteSpace(nextApi))
                    {
                        workflowOutput.NextApi = nextApi;
                    }
                    return workflowOutput;
                }
                else
                {
                    var workflowOutput = await _accountVerifyService.VerifyAsync(userName, password, "报告_移交报告", reports[0].Exam);
                    if (workflowOutput.Success)
                    {
                        var users = reports[0].Exam.Department.UserGroups.SelectMany(e => e.Users);
                        var options = (from a in users
                                       group a by new { a.Id, a.Name } into aGroup
                                       select new
                                       {
                                           Label = aGroup.Key.Name,
                                           Value = aGroup.Key.Id,
                                       }).ToList();
                        string content = string.Empty;
                        if (string.IsNullOrWhiteSpace(content))
                        {
                            content = await Extensions.GetResourceStringAsync("Resources.Report.transfer-view.json");
                        }
                        workflowOutput.ViewTitle = "移交报告";
                        workflowOutput.Content = new
                        {
                            TransferUsers = options
                        };
                        workflowOutput.View = content;
                        if (!string.IsNullOrWhiteSpace(nextApi))
                        {
                            workflowOutput.NextApi = nextApi;
                        }
                        workflowOutput.ViewWidth = "25%";
                    }
                    return workflowOutput;
                }
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> DisassembleAsync(Guid examId, List<Guid> examItemIds)
    {
        try
        {
            var exam = await _examRepository.GetAsync(examId);
            await _examPermissionService.ValidateAsync(exam, isValidateExpertGroup: false);
            var newExam = await CloneExamAsync(exam);
            var examItems = await _examItemRepository.GetListAsync(e => examItemIds.Contains(e.Oid));

            //检查项目
            newExam.ExamItems.AddRange(examItems);
            newExam.ExamItemsText = string.Join(',', newExam.ExamItems);
            newExam.UpdateShared();

            exam.ExamItems.RemoveAll(e => examItemIds.Contains(e.Oid));
            exam.ExamItemsText = string.Join(',', exam.ExamItems);
            exam.UpdateShared();

            //检查申请
            if (exam.ExamApplyItems.Count > 0)
            {
                var examItemCodes = examItems.Select(e => e.OuterCode).ToList();
                var examApplyItems = exam.ExamApplyItems.Where(e => examItemCodes.Contains(e.ExamItemCode)).ToList();
                newExam.ExamApplyItems.AddRange(examApplyItems);
                exam.ExamApplyItems.RemoveAll(e => examItemCodes.Contains(e.ExamItemCode));
            }
            //检查费用
            newExam.ExamFee = newExam.ExamItems.Sum(e => e.Fee);
            exam.ExamFee = exam.ExamItems.Sum(e => e.Fee);
            //检查事件
            await _examEventService.AddExamEventAsync(exam, "拆分检查");
            await _examEventService.AddExamEventAsync(newExam, "来自拆分创建");
            return new WorkflowOutput
            {
                Success = true,
                Data = newExam.Oid
            };
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    public async Task<WorkflowOutput> VerifyUserAsync(WorkflowInput input, string nextApi = null)
    {
        try
        {
            var show = bool.Parse(input.GetValueOrDefault("show")?.ToString());
            var userName = input.GetValueOrDefault("userName")?.ToString();
            var password = input.GetValueOrDefault("password")?.ToString();
            if (show || string.IsNullOrWhiteSpace(userName))
            {
                var workflowOutput = await _accountVerifyService.GetVerifyViewAsync();
                if (!string.IsNullOrWhiteSpace(nextApi))
                {
                    workflowOutput.NextApi = nextApi;
                }
                workflowOutput.Data = new
                {
                    UserName = userName,
                    Show = false
                };
                return workflowOutput;
            }
            else
            {
                var workflowOutput = await _accountVerifyService.VerifyAsync(userName, password, func: (hasPermission, user) =>
                {
                    return new WorkflowOutput
                    {
                        Success = true,
                        Data = new
                        {
                            UserId = user.Id,
                            user.UserName
                        }
                    };
                });
                workflowOutput.Info = "null";
                workflowOutput.ViewTitle = "审核验证";
                return workflowOutput;
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput
            {
                Success = false,
                Error = ex.Message
            };
        }
    }

    private async Task<Exam> CloneExamAsync(Exam exam)
    {
        var cloneExam = await _examRepository.NewEntityAsync();
        _objectMapper.Map(exam, cloneExam);

        cloneExam.ExamMethods.AddRange(exam.ExamMethods);
        cloneExam.ExamBodyParties.AddRange(exam.ExamBodyParties);
        cloneExam.PatientFeatures.AddRange(exam.PatientFeatures);
        cloneExam.ExamFlags.AddRange(exam.ExamFlags);

        foreach (var item in exam.PatientMatters)
        {
            var patientMatter = await _patientMatterRepository.NewEntityAsync();
            patientMatter.Content = item.Content;
            patientMatter.IsStrong = item.IsStrong;
            patientMatter.Order = item.Order;
            cloneExam.PatientMatters.Add(patientMatter);
        }

        foreach (var item in exam.ExamRemarks)
        {
            var remark = await _examRemarkRepository.NewEntityAsync();
            remark.Content = item.Content;
            remark.Level = item.Level;
            remark.User = item.User;
            cloneExam.ExamRemarks.Add(remark);
        }

        if (cloneExam.ExamDevice.EnableGenerateStudyUID)
        {
            cloneExam.StudyInstanceUid = null;
            cloneExam.AccessionNumber = null;
        }
        else
        {
            cloneExam.Studies.AddRange(exam.Studies);
        }

        await _examNumberService.SetNumberAsync(cloneExam, true);

        return cloneExam;
    }

    public async Task<WorkflowOutput> ExportAsync(DataGridRequest request)
    {
        try
        {
            CriteriaOperator criteriaOperator = CriteriaOperator.And(CriteriaOperator.FromLambda<Exam>(e => e.ExamStatus > ExamStatus.Appointment));
            var file = await _exportService.ExportListToFileAsync(request, criteriaOperator, _advancedSearchExpression, _getHeaders, null, ExamFilterType.Exam);
            if (File.Exists(file))
            {
                return new WorkflowOutput()
                {
                    Success = true,
                    Data = _stringEncryptionService.Encrypt(Path.GetFileName(file)),
                };
            }
            else
            {
                return new WorkflowOutput()
                {
                    Success = false,
                    Error = "导出列表失败，请稍后重试"
                };
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
            await _unitOfWorkManager.Current.RollbackAsync();
            return new WorkflowOutput()
            {
                Success = false,
                Error = ex.Message
            };
        }
    }
}
